
package cn.xp1997.shiro.x.token;

import cn.xp1997.shiro.x.constant.TokenConstant;
import cn.xp1997.shiro.x.exception.ShiroTokenException;
import cn.xp1997.shiro.x.jwt.JwtUtil;

import java.lang.reflect.Field;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author xp
 */
public class TokenBuilder {



    private String secret = "";

    private Date date;

    private Map<String, String> keys = new HashMap<>();

    private String infoName;

    private Object object;




    private Date getDate(){
        if(this.date == null){
            this.date = new Date();
        }
        return this.date;
    }

    private String getSecret(){
        return this.secret;
    }

    private Map<String, String> getKeys(){
        return this.keys;
    }

    public String getInfo(){
        return this.infoName;
    }



    public TokenBuilder buildKey(String key, String value){
        getKeys().put(key, value);
        return this;
    }

    public TokenBuilder buildSecret(String secret){
        this.secret = secret;
        return this;
    }

    public TokenBuilder buildInfo(Class infoClass){
        this.infoName = infoClass.getName();
        getKeys().put(TokenConstant.TOKEN_SIGN_KEY_INFO, getInfo());
        return this;
    }

    public TokenBuilder buildDate(Date date){
        this.date = date;
        return this;
    }

    public TokenBuilder buildObject(Object obj){
        this.object = obj;
        return this;
    }


    public String generateTokenFromKeys(){
        checkParam();
        return JwtUtil.sign(getKeys(), getSecret(), getDate());
    }



    public String generateTokenFromObject(){
        Map<String, String> map = getMapFromObject();
        return JwtUtil.sign(map, getSecret(), getDate());
    }

    private Map<String, String> getMapFromObject(){
        checkObject();
        HashMap<String, String> map = new HashMap<>(16);

        //反射获取对象属性
        Class<?> clazz = object.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            String name = field.getName();
            // 私有属性必须设置访问权限
            field.setAccessible(true);
            try {
                Object value = field.get(object);
                if(null != value){
                    map.put(name, value.toString());
                }
            } catch (IllegalAccessException e) {
                throw new ShiroTokenException("error to getObjectValue");
            }
        }
        return map;
    }

    private void checkParam(){
        if(null ==getInfo() || "".equals(getInfo())){
            throw new ShiroTokenException("generate token error (info missing)");
        }
    }

    private void checkObject(){
        if(object == null){
            throw new ShiroTokenException("generate token error (object missing)");
        }
    }

}
